/*
 * JFrame.java
 *
 * Created on December 1, 2007, 4:45 PM
 */

/**
 *
 * @author  Brian
 */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.util.*;
//CHARLES Creative/Humourous and Recreational/Lucrative Expedition System
public class JFrame extends javax.swing.JFrame {
    String versionInfo = "v1.2.1";
    ServerSocket server;
    ClientWorker cw;
    protected ArrayList clients;
    protected MersenneTwister random;
    String DMStatus = "";
    /** Creates new form JFrame */
    public JFrame() {
        try {
            javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());          
        }
        catch (Exception e) {
            //System.out.println(e);
        } 
        initComponents();
        setupServer();
        random = new MersenneTwister();
        paintListener pl = new paintListener();
        
        jTextArea1.append("Welcome. Now listening on port 4433. Type /help for help. Written by Brian Dawn Copyright 2008.");
        //Font f = new Font("airel", Font.PLAIN, 12);
        //jTextArea1.setFont(f);
        //jTextArea1.setWrapStyleWord(true);
        setTitle("CHARLES Server "+versionInfo);
        loadPicDirectory();
    }
    public void loadPicDirectory(){
        File f = new File("images/");
        String[] ffs = null;
        if ( f.exists()  &&  f.isDirectory() ) {
            ffs = f.list();
        }
        for (int i=0; ffs != null  &&  i<ffs.length; i++) {
            jComboBox1.addItem(ffs[i]);
        }
    }
    public void setupServer(){
        clients = new ArrayList();
        try{
            server = new ServerSocket(4433);
            //System.out.println("Listening");
        } catch (IOException e) {
            //System.out.println("Could not listen on port 4444");
            //System.exit(-1);
        }
        ClientListener cl = new ClientListener();
    }  
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jTextField1 = new javax.swing.JTextField();
        jScrollPane2 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        drawingPanel21 = new DrawingPanel2();
        jButton3 = new javax.swing.JButton();
        jComboBox1 = new javax.swing.JComboBox();
        jTextField2 = new javax.swing.JTextField();
        jTextField3 = new javax.swing.JTextField();
        jComboBox2 = new javax.swing.JComboBox();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jTextField4 = new javax.swing.JTextField();
        jComboBox3 = new javax.swing.JComboBox();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jToggleButton1 = new javax.swing.JToggleButton();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jButton4 = new javax.swing.JButton();
        jButton5 = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTextArea1 = new AppendingTextPane();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenu3 = new javax.swing.JMenu();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jTextField1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jTextField1ActionPerformed(evt);
            }
        });
        jTextField1.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                jTextField1KeyPressed(evt);
            }
        });

        jList1.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "The DM" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jList1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jList1MouseClicked(evt);
            }
        });
        jScrollPane2.setViewportView(jList1);

        jButton1.setText("Send");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jButton2.setText("Clear Grid");
        jButton2.setToolTipText("Clear the grid of all icons and drawing.");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        drawingPanel21.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        javax.swing.GroupLayout drawingPanel21Layout = new javax.swing.GroupLayout(drawingPanel21);
        drawingPanel21.setLayout(drawingPanel21Layout);
        drawingPanel21Layout.setHorizontalGroup(
            drawingPanel21Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 757, Short.MAX_VALUE)
        );
        drawingPanel21Layout.setVerticalGroup(
            drawingPanel21Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 197, Short.MAX_VALUE)
        );

        jButton3.setText("Add Icon");
        jButton3.setToolTipText("Add the icon.");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        jComboBox1.setToolTipText("Icon image to use.");

        jTextField2.setText("40");
        jTextField2.setToolTipText("Set the grid size, this will be changed when the grid is cleared.");

        jTextField3.setText("The DM");
        jTextField3.setToolTipText("Name of the icon. Note icons will be assigned to players if it has the same name as them. You can click the players name in the client list to change this quickly.");

        jComboBox2.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1", "3", "5", "8", "15", "22", "40", "200" }));
        jComboBox2.setSelectedIndex(1);
        jComboBox2.setToolTipText("Change the brush size.");
        jComboBox2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jComboBox2ActionPerformed(evt);
            }
        });

        jLabel5.setText("Name");

        jLabel6.setText("Icon");

        jTextField4.setText("The DM");
        jTextField4.setToolTipText("Alter the way your name appears (for NPCs and such).");

        jComboBox3.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Paint Mode - Draw", "Paint Mode - Erase", "Icon Mode" }));
        jComboBox3.setToolTipText("Change the drawing mode.");
        jComboBox3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jComboBox3ActionPerformed(evt);
            }
        });

        jLabel1.setText("Brush Settings");

        jLabel2.setText("Size");

        jToggleButton1.setText("Chat Off");
        jToggleButton1.setToolTipText("Toggle chat on/off. The DM may always speak.");
        jToggleButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleButton1ActionPerformed(evt);
            }
        });

        jLabel3.setText("Grid Size");

        jLabel4.setText("Chat Settings");

        jButton4.setText("Kick");
        jButton4.setToolTipText("Kicks the selected player.");
        jButton4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton4ActionPerformed(evt);
            }
        });

        jButton5.setText("Focus Clients");
        jButton5.setToolTipText("Sets the viewport on the clients to your viewport.");
        jButton5.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton5ActionPerformed(evt);
            }
        });

        jTextArea1.setEditable(false);
        jTextArea1.setFont(new java.awt.Font("Arial", 0, 12));
        jScrollPane1.setViewportView(jTextArea1);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel1Layout.createSequentialGroup()
                                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(jPanel1Layout.createSequentialGroup()
                                        .addComponent(jButton2)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                            .addGroup(jPanel1Layout.createSequentialGroup()
                                                .addComponent(jLabel3)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(jButton5)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))
                                            .addGroup(jPanel1Layout.createSequentialGroup()
                                                .addComponent(jLabel5)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(jTextField3, javax.swing.GroupLayout.DEFAULT_SIZE, 65, Short.MAX_VALUE)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(jLabel6)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(jComboBox1, 0, 102, Short.MAX_VALUE)
                                                .addGap(2, 2, 2)))
                                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                            .addComponent(jLabel4)
                                            .addComponent(jLabel1))
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                            .addGroup(jPanel1Layout.createSequentialGroup()
                                                .addComponent(jComboBox3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(jLabel2)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(jComboBox2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                            .addGroup(jPanel1Layout.createSequentialGroup()
                                                .addComponent(jToggleButton1)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(jButton4))))
                                    .addGroup(jPanel1Layout.createSequentialGroup()
                                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                            .addComponent(jTextField4, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
                                            .addComponent(jButton3))
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 489, Short.MAX_VALUE)))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jButton1))
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 633, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(drawingPanel21, javax.swing.GroupLayout.DEFAULT_SIZE, 759, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jScrollPane2)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 205, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jTextField4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButton1)
                    .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton2)
                    .addComponent(jLabel3)
                    .addComponent(jToggleButton1)
                    .addComponent(jLabel4)
                    .addComponent(jButton4)
                    .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButton5))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton3)
                    .addComponent(jComboBox2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel6)
                    .addComponent(jLabel2)
                    .addComponent(jComboBox3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1)
                    .addComponent(jLabel5)
                    .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(drawingPanel21, javax.swing.GroupLayout.DEFAULT_SIZE, 199, Short.MAX_VALUE))
        );

        jMenu1.setText("File");

        jMenuItem1.setText("Quit");
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem1);

        jMenuBar1.add(jMenu1);

        jMenu3.setText("About");
        jMenuBar1.add(jMenu3);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem1ActionPerformed
        System.exit(-1);
    }//GEN-LAST:event_jMenuItem1ActionPerformed

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        //CreateIcon
        String name = jTextField3.getText();
        String image = (String)jComboBox1.getSelectedItem();
        drawingPanel21.addIcon(10-drawingPanel21.xOffset,10-drawingPanel21.yOffset,image,name);
        iconCreateBroadcast(image, name);
    }//GEN-LAST:event_jButton3ActionPerformed
    public void iconCreateBroadcast(String image, String name){
        int tx = 10 -drawingPanel21.xOffset;
        int ty = 10 -drawingPanel21.yOffset;
        String mesg = "ic*"+image+":"+name+":"+tx+":"+ty; //add size
        for (int i=0; i<clients.size(); i++) {
            ClientWorker sib = (ClientWorker)clients.get(i);
            sib.out.println(mesg);
        }
    }
    private void sendStatus(String name, int typing){
        if (cw!=null)
            cw.broadcast("typ*"+name+":"+typing); //1 = true
    }
    private void jTextField1KeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTextField1KeyPressed
        //the DM is typing!!! notify pl0x
        //FINISH ME
        int typing = 0;
        boolean notSent = true;

        if(jTextField1.getText().length() > 2) notSent = false; //already sent
        if(jTextField1.getText().length() == 0) notSent = false;
        if(jTextField1.getText().length() == 1) notSent = true;
        DMStatus = "";
        if(jTextField1.getText().length() > 0){
            if(jTextField1.getText().length() > 1){
                DMStatus = "Typing.";
                typing = 1;
            }
        }
        if (evt.getKeyCode() == 10){
            DMStatus = "";
            typing = 0;
            send();
            notSent = true;
        }
        if (notSent == true) sendStatus("The DM", typing);

        
        updateList();
    }//GEN-LAST:event_jTextField1KeyPressed
    public boolean DMisHelp(String line){
        try{
            if (line.substring(0,5).equals("/help")){
                jTextArea1.append("<b>COMMANDS</b><br>   /1d6+1 is an example of dice rolling.<br>   //1d20 is an example of private (DM only) dice rolling.");
                jTextArea1.append("<b>CONTROLS</b><br>   Left mouse button is used for drawing/erasing/icon moving.<br>   Middle mouse button is used for drawing straight lines.<br>   Right mouse button is used to move the viewport around.");
                return true;
            }
        }catch(StringIndexOutOfBoundsException e){}
        return false;
    }
    public boolean DMisDice(String line){
        //   /1d6+4
        try{
            if (line.substring(0,2).equals("//")){
                int theRoll = dieRoll(line.substring(2));
                jTextArea1.append("You roll "+theRoll+" on "+line.substring(2)+" (private).");
                //$$jTextArea1.setCaretPosition(jTextArea1.getText().length());
                return true;
            }else{
                if (line.substring(0,1).equals("/")){
                    int theRoll = dieRoll(line.substring(1));
                    jTextArea1.append("The DM has rolled a "+theRoll+" on "+line.substring(1)+".");
                    if (cw!=null)
                        cw.broadcast("The DM has rolled a "+theRoll+" on "+line.substring(1)+".");
                    //$$jTextArea1.setCaretPosition(jTextArea1.getText().length());
                    return true;
                }
            }
        }catch(StringIndexOutOfBoundsException e){}
        return false;
    }    
    private void send(){
        String DMName = jTextField4.getText();
        if(jTextField1.getText().equals("")){
        }else{
            String message = jTextField1.getText(); 
            jTextField1.setText("");
            if(DMisHelp(message) == false){
                if(DMisDice(message) == false){
                    jTextArea1.append("<b>"+DMName+": "+message+"</b>");
                    //$jTextArea1.setCaretPosition(jTextArea1.getText().length());
                    if (cw!=null)
                        cw.broadcast("<b>"+DMName+": "+message+"</b>");
                }
            }
        }
    }
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        send();
    }//GEN-LAST:event_jButton1ActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        int size = Integer.valueOf(jTextField2.getText()).intValue();
        drawingPanel21.wipeGrid(size);
        wipeBroadcast();
    }//GEN-LAST:event_jButton2ActionPerformed

    private void jList1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jList1MouseClicked
        jTextField3.setText((String)jList1.getSelectedValue());
    }//GEN-LAST:event_jList1MouseClicked

    private void jComboBox2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox2ActionPerformed
        drawingPanel21.setBrushSize(jComboBox2.getSelectedItem());
        if(drawingPanel21.penColor == Color.black){
            paintEditBroadcast(false);
        }else{
            paintEditBroadcast(true);
        }
    }//GEN-LAST:event_jComboBox2ActionPerformed

    private void jComboBox3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox3ActionPerformed
        String get = (String)jComboBox3.getSelectedItem();
        if(get == "Icon Mode"){
            drawingPanel21.moveMode = 1;
        }
        if(get == "Paint Mode - Draw"){
            drawingPanel21.moveMode = -1;
            int brushSize = drawingPanel21.setEraseMode(Color.black);
            String s = "" + brushSize;
            Object obj = (Object)s;
            jComboBox2.setSelectedItem(obj);
            paintEditBroadcast(false);
        }
        if(get == "Paint Mode - Erase"){
            drawingPanel21.moveMode = -1;
            int brushSize = drawingPanel21.setEraseMode(Color.white);
            String s = "" + brushSize;
            Object obj = (Object)s;
            jComboBox2.setSelectedItem(obj);
            paintEditBroadcast(true);
        }
    }//GEN-LAST:event_jComboBox3ActionPerformed

    private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField1ActionPerformed

    }//GEN-LAST:event_jTextField1ActionPerformed

    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed
        //KICK BUTTON PRESSED
        String listSelect = (String)jList1.getSelectedValue();
        for (int i=0; i<clients.size(); i++) {
            ClientWorker sib = (ClientWorker)clients.get(i);
            
            if(sib.clientName.equals(listSelect)){
                    sib.out.println("You have been kicked.");
                    sib.kill = true;
                    sib.out.close();
                    clients.remove(this);
                    updateList();
                    sib.broadcast(sib.clientName+" has been kicked.");
                    sib.broadcastLeave();
                    jTextArea1.append(sib.clientName+" has been kicked.");
            }
        }        
    }//GEN-LAST:event_jButton4ActionPerformed

    private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleButton1ActionPerformed
        //CHAT off
        if(jToggleButton1.isSelected()){
            if (cw!=null)
                cw.broadcast("noc*1");
            jTextArea1.append("<i>(Chat disabled.)");
        }else{
            if (cw!=null)
                cw.broadcast("noc*0"); 
            jTextArea1.append("<i>(Chat enabled.)");
        }
    }//GEN-LAST:event_jToggleButton1ActionPerformed

    private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton5ActionPerformed
        if (cw!=null)
            cw.broadcast("res*"+drawingPanel21.getCenterOffsets()); 
    }//GEN-LAST:event_jButton5ActionPerformed
    public void paintEditBroadcast(boolean erase){
        //p*[erase 1 if true 0 if not]:[pensize]
        String tOut = "p*";
        Color get = drawingPanel21.penColor;
        tOut += erase + ":";
        tOut += jComboBox2.getSelectedItem();
        for (int i=0; i<clients.size(); i++) {
            ClientWorker sib = (ClientWorker)clients.get(i);
            sib.out.println(tOut);
        }
    } 
    public void wipeBroadcast(){
        //w*[gridsize]
        String tOut = "w*";
        tOut += jTextField2.getText();
        for (int i=0; i<clients.size(); i++) {
            ClientWorker sib = (ClientWorker)clients.get(i);
            sib.out.println(tOut);
        }
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new JFrame().setVisible(true);
            }
        });
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private DrawingPanel2 drawingPanel21;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;
    private javax.swing.JButton jButton5;
    private javax.swing.JComboBox jComboBox1;
    private javax.swing.JComboBox jComboBox2;
    private javax.swing.JComboBox jComboBox3;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JList jList1;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private AppendingTextPane jTextArea1;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextField jTextField2;
    private javax.swing.JTextField jTextField3;
    private javax.swing.JTextField jTextField4;
    private javax.swing.JToggleButton jToggleButton1;
    // End of variables declaration//GEN-END:variables
    class paintListener implements Runnable{
        int hx,hy,hx2,hy2;
        Thread t;
        
        paintListener(){
            Thread t = new Thread(this);
            t.start();
        }
        public void run(){
            while(true){
                lineBroadcast();
                iconBroadcast();
                pointerBroadcast();
                try{
                    t.sleep(10);
                }catch (Exception e) {}
            }
        }
        public void iconBroadcast(){
            int x = drawingPanel21.iconSX; int y = drawingPanel21.iconSY;
            String mesg = "i*"+x+":"+y+":"+drawingPanel21.selectedIcon;
            if(x!=0 && y!=0 && drawingPanel21.selectedIcon!=-1){
                drawingPanel21.iconSX = 0;
                drawingPanel21.iconSY = 0;
                drawingPanel21.selectedIcon = -1;
                for (int i=0; i<clients.size(); i++) {
                    ClientWorker sib = (ClientWorker)clients.get(i);
                    sib.out.println(mesg);
                }
            }
        }
        public void pointerBroadcast(){
            if (drawingPanel21.sendPointX != -1){
                String mesg = "pp*" + drawingPanel21.sendPointX + ":" + drawingPanel21.sendPointY;
                for (int i=0; i<clients.size(); i++) {
                    ClientWorker sib = (ClientWorker)clients.get(i);
                    sib.out.println(mesg);
                }
                drawingPanel21.sendPointX = -1;
                drawingPanel21.sendPointY = -1;
            }
            
        }
        public void lineBroadcast(){
            //int x = drawingPanel21.sendX; int y = drawingPanel21.sendY;
            //int x2 = drawingPanel21.sendHx; int y2 = drawingPanel21.sendHy;
            //String mesg = "c*"+x+":"+y+":"+x2+":"+y2;
            if (drawingPanel21.lineCounter > 200 && drawingPanel21.lineStorage != ""){
                drawingPanel21.lineCounter = 0;
                String mesg = "c*" + drawingPanel21.lineStorage;
                drawingPanel21.lineStorage = "";
            //if(x2!=hx || y2!=hy || hx2!=x || hy2!=y){
            //if(x2!=0 && y2!=0 && x!=0 && y!=0){
                //hx=x2; hy=y2; hx2=x; hy2=y;
                for (int i=0; i<clients.size(); i++) {
                    ClientWorker sib = (ClientWorker)clients.get(i);
                    sib.out.println(mesg);
                }
                //drawingPanel21.sendPointX = drawingPanel21.sendX;
                //drawingPanel21.sendPointY = drawingPanel21.sendY;
            //}
            //}
            }
        }
    }
    public int dieRoll(String inp){
        try{
            int total = 0;
            String string = inp.toUpperCase();
            String array1[] = string.split(" ");
            for (int x=0; x < array1.length; x++) {
                String array2[] = array1[x].split("D");
                if (array2.length == 2){ //VALIDITY CHECK
                    String array3[] = array2[1].split("\\+");
                    String array32[] = array2[1].split("\\-");
                    int addon = 0;
                    if (array3.length == 2){
                        addon = Integer.parseInt(array3[1]);
                        array2[1] = array3[0];
                    }
                    if (array32.length == 2){
                        addon = Integer.parseInt(array32[1])*-1;
                        array2[1] = array32[0];
                    }
                    int rolls = Integer.parseInt(array2[0]);
                    int value = Integer.parseInt(array2[1]);
                    int theRoll;
                    for (int z=0; z < rolls; z++){
                        if(value < 1000){
                            theRoll = random.nextInt(value);
                            total = total + theRoll + 1; //Add 1, as it will count 0 then
                        }
                    }
                    total = total + addon;
                }
            }
            return total;
        }catch(NumberFormatException e){}
        return 0;
    }
    void updateList(){
        String theList = "The DM";
        if (DMStatus != "") theList+=" -"+ DMStatus;
        for (int i=0; i<clients.size(); i++) {
            ClientWorker sib = (ClientWorker)clients.get(i);
            theList+=":;;"+sib.clientName;
            if (sib.clientStatus != "") theList+=" -"+ sib.clientStatus;
        }
        jList1.setListData(theList.split(":;;"));
    }
    class ClientListener implements Runnable {
        Thread t;
        
        ClientListener(){
            Thread t = new Thread(this);
            t.start();
        }
        public void run(){
            while(true){
                ClientWorker w;
                try{
                    cw = new ClientWorker(server.accept());
                    synchronized (clients) {
                        clients.add(cw);
                        cw.startRun();
                    }
                } catch (IOException e) {}
                try{
                    t.sleep(10);
                }catch (Exception e) {}
            }            
        }   
    }
    class ClientWorker implements Runnable {
        private Socket client;
        private BufferedReader in = null;
        private PrintWriter out = null;
        
        Thread t;
        String clientName;
        String clientStatus = ""; //typing etc.
        boolean kill = false;
        ClientWorker(Socket client) {
            this.client = client;
            Thread t = new Thread(this);
            t.start();
        }
        public void startRun(){
            //t.start();
        }
        public void broadcast(String mesg) {
            for (int i=0; i<clients.size(); i++) {
                    //System.out.println(i);
                    ClientWorker sib = (ClientWorker)clients.get(i);
                    sib.out.println(mesg);
            }
        }
    public void broadcastLimited(String mesg) { //send to all but this client
            for (int i=0; i<clients.size(); i++) {
                    //System.out.println(i);
                    ClientWorker sib = (ClientWorker)clients.get(i);
                    if (sib.clientName != this.clientName){
                        sib.out.println(mesg);
                    }
            }
        }
        public void broadcastLeave(){
            broadcast("L*"+clientName);
        }
        public void run(){
            String line;
            boolean stop = false;
            try{
                in = new BufferedReader(new InputStreamReader(client.getInputStream()));
                out = new PrintWriter(client.getOutputStream(), true);
            } catch (IOException e) {
                //.out.println("in or out failed");
                //System.exit(-1);
            }
            line = "";
            String clientInfo = "";
            while(stop!=true){ //Client wait
                if (clientInfo != ""){
                    clientName = clientInfo;
                    broadcast(clientInfo+" has joined.");
                    jTextArea1.append(clientInfo+" has joined.");
                    //$$jTextArea1.setCaretPosition(jTextArea1.getText().length());
                    break;
                }
                try{
                    clientInfo = in.readLine();
                }catch(IOException e){
                }
            }
            out.println("");
            broadcast("n*"+clientInfo); //NAME CONFIRMED SEND TO OTHERS
            updateList();
            //Send members to the client
            String tOut = "q*The DM";
            for (int i=0; i<clients.size();i++){
                ClientWorker sib = (ClientWorker)clients.get(i);
                tOut+=":"+sib.clientName;
            }
               out.println(tOut);
            while(stop!=true && kill == false){
               try{ //MOVED
                if(line != ""){
                    //DICE ROLL
                    if(isDice(line) == false){
                        if(isIconMove(line) == false){
                            if(isTypeChange(line) == false){
                                broadcast(clientName+": "+line);
                                jTextArea1.append(clientName+": "+line);
                                //$$jTextArea1.setCaretPosition(jTextArea1.getText().length());
                            }
                        }
                    }
                }
                //try{ MOVED
                    line="";
                    line = in.readLine();
                    //System.out.println("CLIENT: "+line);
                }catch (RuntimeException e) {
                    //stop=true;
                    //clients.remove(this);
                    //updateList();
                    //broadcastLeave();
                    jTextArea1.append(clientName+" has died by the stupid error. "+e.getMessage()+" but might still live!");
                    //$$jTextArea1.setCaretPosition(jTextArea1.getText().length());                   
                } catch (IOException e) {
                    //System.out.println("Read failed");
                    //System.exit(-1); KILL THREAD
                    stop=true;
                    out.close();
                    clients.remove(this);
                    updateList();
                    broadcastLeave();
                    jTextArea1.append(clientName+" has left.");
                    //$$jTextArea1.setCaretPosition(jTextArea1.getText().length());
                }
                //try{
                    //t.sleep(10);
                //}catch (Exception e) {}
            }
        }
        public boolean isTypeChange(String line){
            //   /1d6+4
            try{
                String[] splitS = line.split("\\*");
                if(splitS[0].equals("typ")){
                    int typeTrue = Integer.valueOf(splitS[1]).intValue();
                    sendStatus(clientName, typeTrue);
                    if(typeTrue==1){
                        clientStatus = "Typing.";
                    }else{
                        clientStatus = "";
                    }
                    updateList();
                    return true;
                }
            }catch(RuntimeException e){}
                return false;
        }
        public boolean isDice(String line){
            //   /1d6+4
            try{
                if (line.substring(0,1).equals("/")){
                    int theRoll = dieRoll(line.substring(1));
                    jTextArea1.append(clientName+" has rolled a "+theRoll+" on "+line.substring(1)+".");
                    broadcast(clientName+" has rolled a "+theRoll+" on "+line.substring(1)+".");
                    //$$jTextArea1.setCaretPosition(jTextArea1.getText().length());
                    return true;
                }
            }catch(RuntimeException e){}
                return false;
        }
        public boolean isIconMove(String line){
            //i*x:y:id
            try{
                String[] splitS = line.split("\\*");
                if(splitS[0].equals("i")){
                    String[] split2 = splitS[1].split(":");
                    int x = Integer.valueOf(split2[0]).intValue();
                    int y = Integer.valueOf(split2[1]).intValue();  
                    int id = Integer.valueOf(split2[2]).intValue(); 
                    drawingPanel21.moveIcon(x,y,id);
                    broadcast(line);
                    return true;
                }
            }catch(NumberFormatException e){
            }catch(RuntimeException e){}
            return false;
        }
    }
}


